/*
 *  Copyright 2012 yura.
 * 
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 * 
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  under the License.
 */

package org.opu.odg.dg.xml;

import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import java.io.StringReader;
import java.util.Properties;
import javax.xml.parsers.SAXParserFactory;
import org.opu.odg.dg.util.ObjectHolder;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 *
 * @author yura
 */
public class XmlParser {
    
    private static final SAXParserFactory factory = SAXParserFactory.newInstance();

    public static ContentMapping parseDocument(InputSource inputSource)
            throws SAXException, IOException {
        final ContentMapping cm = new ContentMapping();
        final ObjectHolder<XmlTag> root = new ObjectHolder<XmlTag>();
        final ObjectHolder<XmlTag> current = new ObjectHolder<XmlTag>();

        SAXParser sp = null;
        try {
            sp = factory.newSAXParser();
        } catch (ParserConfigurationException ex) {
            throw new SAXException(ex);
        }
        sp.parse(inputSource, new DefaultHandler(){

            @Override
            public void startElement(String uri, String localName,
                    String qName, Attributes attributes) throws SAXException {
                if (current.getObject() != null) {
                    current.setObject(current.getObject().addChildren(newTag(
                            current.getObject(), qName, attributes)));
                } else {
                    if (root.getObject() != null) {
                        throw new RuntimeException();
                    }
                    current.setObject(newTag(current.getObject(), qName, attributes));
                    root.setObject(current.getObject());
                }
            }

            @Override
            public void endElement(String uri, String localName, String qName)
                    throws SAXException {
                current.setObject(current.getObject().getParent());
            }

            @Override
            public void characters(char[] ch, int start, int length) throws SAXException {
                String string = new String(ch, start, length);
                TextElement txt = new TextElement(string, current.getObject());
                current.getObject().addChildren(txt);
                cm.addContentEntry(txt);
            }

        });

        cm.setRoot(root.getObject());

        return cm;
    }

    public static ContentMapping parseDocument(String xmlString)
            throws SAXException, ParserConfigurationException, IOException {
        return parseDocument(new InputSource(new StringReader(xmlString)));
    }

    private static XmlTag newTag(XmlTag root, String qName, Attributes attributes) {
        Properties prop = new Properties();
        for(int i = 0; i < attributes.getLength(); i++) {
            prop.setProperty(attributes.getQName(i), attributes.getValue(i));
        }
        return new XmlTag(root, qName, prop);
    }
}
